import { ContainerController } from './../container/container.controller';
import * as dayjs from 'dayjs';
import { whereAndOrderQueryBuilder } from '@/common/tool/sqlbuilder';
import { DeleteDto, FormFieldSelectOption, ResponseJson, SqlQueryDto } from "@/common/type/app.dto";
import { Cntr, CntrInPlan, CntrPlanCntr, CntrFixItem, FixReply, VCntr, CntrOutPlan, CntrPlan, CntrPlanFee, CntrLeasePlan, CntrRentPlan, CntrLease } from "@/container/entities/container.entity";
import { CrudService } from "@/shared/crud.service";
import { SharedService } from "@/shared/shared.service";
import { Injectable } from "@nestjs/common";
import { InjectDataSource } from "@nestjs/typeorm";
import { DataSource } from "typeorm";
import { CntrLeaseDto, CreateCntrDto, PortCntrStatDto, QueryPlanCntrsDto } from '@/container/dto/create-container.dto';
import { RepairStatusType, ResponseCode } from "@/common/type/enum";
import { CntrFixItemDto, DeleteCntrFixItemsDto, GateInCntrDto, GateOutCntrDto, RentInCntrDto, UpdateCntrFixItemDto } from "./dto/cfs.dto";
import { findIndex, isNil, omit } from "lodash";
import { FeedetDto } from "@/business/dto/create-business.dto";
import { ContainerService } from "@/container/container.service";
import { BusinessService } from "@/business/business.service";
import { EmailType } from "@/common/type/app";
import { Client, CyCfs, Scode } from "@/basedata/entities/basedatum.entity";
import { LeaseCntrBackDto, UpdateLeaseCntrDto } from '@/container/dto/update-container.dto';
import { EIDXJC, EITZJC, EIZYXT, EODXCC, EOQZCC } from '@/common/const/CntrStat';

@Injectable()
export class CfsService {
    constructor(
        @InjectDataSource() private datasource: DataSource,
        private crud: CrudService,
        private sharedService: SharedService,
        private containerService: ContainerService,
        private businessService: BusinessService
    ) { }
    async queryCntr(
        query: SqlQueryDto,
        cfs_id: number
    ): Promise<ResponseJson<VCntr[], number>> {
        query.where['cfs_cod'] = { equals: cfs_id };
        return await this.crud.query<VCntr>(VCntr, query);
    }
    /**
     * 箱查询导出
     * @param query
     * @returns
     */
    async exportQueryCntr(
        query: SqlQueryDto, cfs_id: number
    ): Promise<ResponseJson<string, null>> {
        query.where['cfs_cod'] = { equals: cfs_id };
        return this.sharedService.exportQueryToExcel<VCntr>(VCntr, query, {
            current_stat: 'CntrStatus',
            cfs_cod: 'Cfs',
            cntr_oper_cod: 'ClientKeyValue',
            cntr_corp_cod: 'ClientKeyValue',
            cntr_owner: 'ClientKeyValue',
        });
    }
    /**
     * 查询堆场未完成进场计划
     * @param query 
     * @returns 
     */
    async queryCntrInPlan(
        query: SqlQueryDto, cfs_id: number
    ): Promise<ResponseJson<CntrInPlan[], number>> {
        query['where'] = {
            cfs_cod: {
                equals: cfs_id
            },
            finish_id: {
                equals: 'N'
            },
            carry_id: {
                equals: 'A'
            }
        }

        /* query.left = [
            {
                property: 'v_truck_cntr_inplan.fees',
                alias: 'truck_cntr_plan_fee',
            },
        ]; */
        return await this.crud.query<CntrInPlan>(CntrInPlan, query);
    }
    /**
     * 查询堆场未完成出场计划
     * @param query 
     * @returns 
     */
    async queryCntrOutPlan(
        query: SqlQueryDto, cfs_id: number
    ): Promise<ResponseJson<CntrOutPlan[], number>> {
        query['where'] = {
            cfs_cod: {
                equals: cfs_id
            },
            finish_id: {
                equals: 'N'
            },
            carry_id: {
                equals: 'T'
            }
        }

        /* query.left = [
            {
                property: 'v_truck_cntr_inplan.fees',
                alias: 'truck_cntr_plan_fee',
            },
        ]; */
        return await this.crud.query<CntrOutPlan>(CntrOutPlan, query);
    }
    /**
     * 查询堆场未完成起租计划
     * @param query 
     * @returns 
     */
    async queryCntrLeasePlan(
        query: SqlQueryDto, cfs_id: number
    ): Promise<ResponseJson<CntrLeasePlan[], number>> {
        query['where'] = {
            cfs_cod: {
                equals: cfs_id
            },
            finish_id: {
                equals: 'N'
            },
            carry_id: {
                equals: 'S'
            }
        }

        /* query.left = [
            {
                property: 'v_truck_cntr_inplan.fees',
                alias: 'truck_cntr_plan_fee',
            },
        ]; */
        return await this.crud.query<CntrLeasePlan>(CntrLeasePlan, query);
    }
    /**
     * 查询堆场未完成退租计划
     * @param query 
     * @returns 
     */
    /* async queryCntrRentPlan(
       query: SqlQueryDto, cfs_id: number
   ): Promise<ResponseJson<CntrOutPlan[], number>> {
       query['where'] = {
           cfs_cod: {
               equals: cfs_id
           },
           finish_id: {
               equals: 'N'
           },
           carry_id: {
               equals: 'E'
           }
       }

       
       return await this.crud.query<CntrRentPlan>(CntrRentPlan, query);
   }  */
    /**
     * 
     * @param dto 
     * @param cfs_id 
     * @returns 
     */
    async queryUnusedPreCntrsByPlan(dto: QueryPlanCntrsDto, cfs_id: number): Promise<
        ResponseJson<
            Array<FormFieldSelectOption>,
            null
        >
    > {
        // const result: Array<FormFieldSelectOption> = [];
        const plan = await this.datasource.manager.createQueryBuilder<CntrPlan>(CntrPlan, 'truck_cntr_plan')
            .select('cfs_cod', 'cfs_cod')
            .where('id = :id', { id: dto.plan_id })
            .getRawOne();

        if (plan?.cfs_cod === cfs_id) {
            const precntrs = await this.datasource.manager.createQueryBuilder<CntrPlanCntr>(CntrPlanCntr, 'truck_cntr_plan_cntr')
                .select(['cntr as label', 'cntr as value'])
                .where('truck_sn = :truck_sn', { truck_sn: dto.plan_id })
                .andWhere("used_id = 'N'")
                .getRawMany();
            return {
                code: ResponseCode.SuccessNoMsg,
                obj: precntrs
            }
        } else {
            throw new Error('非此站点计划');
        }

    }

    async gatein(dto: GateInCntrDto, cfs_id: number, oper_nam: string): Promise<ResponseJson<null, null>> {
        const queryRunner = this.datasource.createQueryRunner();
        await queryRunner.connect();
        await queryRunner.startTransaction();
        try {
            const findPlan = await queryRunner.manager
                .createQueryBuilder<CntrInPlan>(
                    CntrInPlan,
                    'v_truck_cntr_inplan',
                )
                .select([
                    'v_truck_cntr_inplan.cntr_siz_cod',
                    'v_truck_cntr_inplan.cntr_typ_cod',
                    'v_truck_cntr_inplan.cntr_oper_cod',
                    'v_truck_cntr_inplan.in_reason',
                    'v_truck_cntr_inplan.cfs_cod',
                    'v_truck_cntr_inplan.bill_no',
                    'v_truck_cntr_inplan.cntr_owner',
                    'v_truck_cntr_inplan.cntr_num',
                    'v_truck_cntr_inplan.cntr_work_num',
                    'v_truck_cntr_inplan.finish_id',
                ])
                .leftJoinAndSelect(
                    'v_truck_cntr_inplan.fees',
                    'truck_cntr_plan_fee',
                )
                .where('v_truck_cntr_inplan.id = :id', { id: dto.in_truck_sn })
                .getOne();
            if (findPlan.finish_id === 'Y') {
                throw new Error("此计划已完成");
            }
            const maxCntrNum = findPlan.cntr_num - (findPlan.cntr_work_num ?? 0);
            if (maxCntrNum === 0) {
                throw new Error("此计划已完成");
            }
            // 检查预定箱号
            const [preCntrs, preCntrsCount] = await queryRunner.manager.createQueryBuilder<CntrPlanCntr>(CntrPlanCntr, 'truck_cntr_plan_cntr')
                .where('truck_sn = :truck_sn', { truck_sn: dto.in_truck_sn })
                .andWhere("used_id = 'N'")
                .getManyAndCount();
            const find = findIndex(preCntrs, (preCntr) => {
                return preCntr.cntr === dto.cntr;
            })
            if (find === -1 && preCntrsCount > 0) {
                throw new Error('此计划存在预定箱号，请先进场预定箱号或将此箱号添加到预定箱中');
            }
            // 检查站点
            if (!(findPlan?.cfs_cod === cfs_id)) {
                throw new Error('非此站点计划');
            }


            const cntrObj = {} as unknown as CreateCntrDto;
            const feedetObj = {} as unknown as FeedetDto;
            Object.assign(cntrObj, dto);
            cntrObj.current_stat = '2';
            cntrObj.dam_id = dto.dam_id;
            cntrObj.cntr_siz_cod = findPlan.cntr_siz_cod;
            cntrObj.cntr_typ_cod = findPlan.cntr_typ_cod;
            cntrObj.cntr_oper_cod = findPlan.cntr_oper_cod;
            cntrObj.in_reason = findPlan.in_reason;
            cntrObj.cfs_cod = findPlan.cfs_cod;
            cntrObj.bill_no = dto.bill_no ?? findPlan.bill_no;
            cntrObj.cntr_owner = findPlan.cntr_owner;

            // console.log('cntrObj', cntrObj);

            /* if (new Date(cntrObj.to_port_tim).toDateString() !== new Date().toDateString()) {
                throw new Error(`箱号${cntrObj.cntr}进场日期与当前日期不一致`)
            } */
            // 生成cntr_file
            const cntr_no = await this.containerService.createCntr(queryRunner, cntrObj);
            if (cntr_no === 0) {
                throw new Error(`箱号${cntrObj.cntr}进场错误`);
            }

            // 创建箱动态
            const cntrStatObj = {} as unknown as PortCntrStatDto;
            cntrStatObj.cntr_no = cntr_no;
            cntrStatObj.cntr = cntrObj.cntr;
            // cntrStatObj.current_stat = '2';
            // cntrStatObj.cntr_stat_cod = EIDXJC;
            cntrStatObj.cntr_stat_cod = dto.stat_cod;
            cntrStatObj.stat_tim = cntrObj.to_port_tim;
            cntrStatObj.cfs_cod = findPlan.cfs_cod;
            cntrStatObj.plan_id = dto.in_truck_sn;
            cntrStatObj.dam_id = dto.dam_id;
            await this.containerService.createPortCntrStat(cntrStatObj, queryRunner);

            // 生成 fee_det
            for (
                let index = 0;
                index < findPlan.fees.length;
                index++
            ) {
                const element = findPlan.fees[index];
                // feedetObj.in_truck_sn = palnID;
                if (['0105', '0108'].includes(element.fee_cod)) {
                    continue;
                }
                feedetObj.cntr_no = cntr_no;
                feedetObj.fee_owner = element.fee_owner;
                feedetObj.fee_typ_cod = element.fee_typ_cod;
                feedetObj.fee_cod = element.fee_cod;
                feedetObj.fee_unit_cod = element.fee_unit_cod;
                feedetObj.amount = element.amount;
                feedetObj.currency_cod = element.currency_cod;
                feedetObj.fee_nam = oper_nam;
                feedetObj.fee_tim = cntrObj.to_port_tim;
                feedetObj.fee_in_out = element.fee_in_out;
                feedetObj.lease_sn = dto.in_truck_sn;
                await this.businessService.createFeedet(
                    feedetObj,
                    queryRunner,
                );
            }
            await queryRunner.manager
                .createQueryBuilder()
                .update(CntrInPlan)
                .set({
                    cntr_work_num: (findPlan.cntr_work_num ?? 0) + 1,
                    finish_id:
                        (findPlan.cntr_work_num ?? 0) + 1 >=
                            findPlan.cntr_num
                            ? 'Y'
                            : 'N',
                })
                .where('id = :id', { id: dto.in_truck_sn })
                .execute();
            await queryRunner.manager.createQueryBuilder()
                .update(CntrPlanCntr)
                .set({
                    used_id: 'Y'
                })
                .where('truck_sn = :truck_sn', { truck_sn: dto.in_truck_sn })
                .andWhere('cntr = :cntr', { cntr: dto.cntr })
                .execute();
            await queryRunner.commitTransaction();
            // 发送邮件  箱主
            const mailOption: EmailType = {};
            const ownermail = await this.datasource.createQueryBuilder()
                .select(['email', 'client_nam_c'])
                .from(Client, 'c_client_cod')
                .where('id = :id', { id: findPlan.cntr_owner })
                .getRawOne();
            const cfsmail = await this.datasource.createQueryBuilder()
                .select(['email', 'cfs_nam_c'])
                .from(CyCfs, 'c_cy_cfs')
                .where('id = :id', { id: findPlan.cfs_cod })
                .getRawOne();

            if (ownermail?.email) {
                mailOption.to = `${ownermail['email']}`;
                mailOption.subject = '箱进场';
                mailOption.text = `
                        进场计划号：${cntrObj.in_truck_sn}
                        进场时间： ${dayjs(cntrObj.to_port_tim).format('YYYY-MM-DD HH:mm:ss')}
                        箱号: ${cntrObj.cntr}
                        尺寸： ${cntrObj.cntr_siz_cod}
                        箱型： ${cntrObj.cntr_typ_cod}
                        堆场： ${cfsmail.cfs_nam_c}
                    `;
                const sendR = await this.sharedService.sendMail(mailOption);
            }
            return {
                code: ResponseCode.SuccessWithInfo,
                msg: ['进场成功']
            }
        } catch (err) {
            await queryRunner.rollbackTransaction();
            throw err;
        } finally {
            await queryRunner.release();
        }
    }
    /**
     * 箱出场
     * @param dto 
     * @param cfs_id 
     * @param oper_nam 
     * @returns 
     */
    async gateout(dto: GateOutCntrDto, cfs_id: number, oper_nam: string): Promise<ResponseJson<null, null>> {
        const queryRunner = this.datasource.createQueryRunner();
        await queryRunner.connect();
        await queryRunner.startTransaction();
        try {
            // 计划信息
            const findPlan = await queryRunner.manager.createQueryBuilder<CntrOutPlan>(CntrOutPlan, 'v_truck_cntr_outplan')
                .select(['cntr_num', 'cntr_corp_cod', 'cntr_owner', 'cntr_work_num', 'bill_no', 'cfs_cod', 'finish_id',
                    'cntr_siz_cod', 'cntr_typ_cod', 'dam_id', 'stat_cod'])
                .where('id = :id', { id: dto.out_truck_sn })
                .getRawOne();
            // 计划费用信息
            const planFees = await queryRunner.manager.createQueryBuilder<CntrPlanFee>(CntrPlanFee, 'truck_cntr_plan_fee')
                .where('truck_sn = :truck_sn', { truck_sn: dto.out_truck_sn })
                .getMany();

            if (isNil(findPlan)) {
                throw new Error('未选择计划， 出场失败');
            }
            if (findPlan.finish_id === 'Y') {
                throw new Error(`出场计划${dto.out_truck_sn}已完成，出场失败`);
            }
            if (findPlan.cntr_num < ((findPlan.cntr_work_num ?? 0) + dto.cntrs.length)) {
                throw new Error(`出场箱量超过未完成箱量，出场失败`);
            }

            for (let index = 0; index < dto.cntrs.length; index++) {
                const cntrString = dto.cntrs[index];
                const planCntr = await queryRunner.manager.createQueryBuilder<CntrPlanCntr>(CntrPlanCntr, 'truck_cntr_plan_cntr')
                    .select(['id'])
                    .where('truck_sn = :truck_sn', { truck_sn: dto.out_truck_sn })
                    .andWhere('cntr = :cntr', { cntr: cntrString })
                    .andWhere("used_id = 'N'")
                    .getRawOne();
                const cntr = await queryRunner.manager.createQueryBuilder<Cntr>(Cntr, 'cntr_file')
                    .select(['id', 'cfs_cod', 'cntr_owner', 'cntr_siz_cod', 'cntr_typ_cod', 'dam_id'])
                    .where('cntr = :cntr', { cntr: cntrString })
                    .andWhere("current_stat = '2'")
                    .getRawOne();
                if (isNil(cntr)) {
                    throw new Error(`箱号${cntrString}非在场箱， 出场失败`);
                }
                if (isNil(planCntr)) {
                    throw new Error(`箱号${cntrString}非计划预订箱，出场失败`);
                }
                if (!(cntr.cfs_cod === cfs_id && findPlan.cfs_cod === cfs_id)) {
                    throw new Error(`箱号${cntrString}与计划站点不一致， 出场失败`);
                }
                if (cntr.cntr_siz_cod !== findPlan.cntr_siz_cod) {
                    throw new Error(`箱号${cntrString}与计划尺寸不一致， 出场失败`);
                }
                if (cntr.cntr_typ_cod !== findPlan.cntr_typ_cod) {
                    throw new Error(`箱号${cntrString}与计划箱型不一致， 出场失败`);
                }
                // 2024-10-17 coco 通知去掉
                /* if (cntr.dam_id !== findPlan.dam_id) {
                    throw new Error(`箱号${cntrString}与计划箱况不一致， 出场失败`);
                } */
                if (cntr.cntr_owner !== findPlan.cntr_owner) {
                    throw new Error(`箱号${cntrString}与计划箱主不一致， 出场失败`);
                }
                const cntrUpdateObj = { id: cntr.id, cfs_cod: null };

                switch (findPlan.stat_cod) {
                    case EODXCC:   //箱出场
                        Object.assign(cntrUpdateObj, {
                            out_truck_sn: dto.out_truck_sn,
                            release_no: findPlan.bill_no,
                            cntr_corp_cod: findPlan.cntr_corp_cod,
                            leav_port_tim: dto.leav_port_tim,
                            out_truck_no_c: dto.out_truck_no_c,
                            out_truck_tel: dto.out_truck_tel,
                        });
                        break;
                    case EOQZCC:   // 起租出场
                        /* Object.assign(cntrUpdateObj, {
                            current_stat: '1',
                        }); */
                        const leaseCntr = {} as unknown as CntrLeaseDto;
                        leaseCntr.cntr_no = cntr.id;
                        leaseCntr.lease_sn = dto.out_truck_sn;
                        leaseCntr.out_date = dto.leav_port_tim;
                        leaseCntr.out_cfs = cntr.cfs_cod;
                        leaseCntr.out_truck_no_c = dto.out_truck_no_c;
                        leaseCntr.out_driver_tel = dto.out_truck_tel;
                        // 插入 cntr_lease 新记录
                        await this.containerService.createCntrLease(leaseCntr, queryRunner);
                        break;
                    default:
                        break;
                }
                // 修改cntr_file
                await this.containerService.updateCntr(
                    cntrUpdateObj,
                    queryRunner,
                );
                // 创建箱动态
                const cntrStatObj = {} as unknown as PortCntrStatDto;
                cntrStatObj.cntr_no = cntr.id;
                cntrStatObj.cntr = cntrString;
                // cntrStatObj.current_stat = '2';
                cntrStatObj.cntr_stat_cod = findPlan.stat_cod;
                cntrStatObj.stat_tim = dto.leav_port_tim;
                cntrStatObj.cfs_cod = findPlan.cfs_cod;
                cntrStatObj.plan_id = dto.out_truck_sn;
                cntrStatObj.truck_no = dto.out_truck_no_c;
                cntrStatObj.driver_tel = dto.out_truck_tel;
                cntrStatObj.dam_id = cntr.dam_id;
                await this.containerService.createPortCntrStat(cntrStatObj, queryRunner);


                await queryRunner.manager.createQueryBuilder()
                    .update(CntrPlanCntr)
                    .set({
                        used_id: 'Y'
                    })
                    .where('id = :id', { id: planCntr.id })
                    .execute();
                // 产生费用
                for (let index = 0; index < planFees.length; index++) {
                    const feedetObj = {} as unknown as FeedetDto;
                    const element = planFees[index];
                    if (['0105', '0108'].includes(element.fee_cod)) {
                        continue;
                    }
                    // feedetObj.out_truck_sn = planID;
                    feedetObj.cntr_no = cntr.id;
                    feedetObj.fee_owner = element.fee_owner;
                    feedetObj.fee_typ_cod = element.fee_typ_cod;
                    feedetObj.fee_cod = element.fee_cod;
                    feedetObj.fee_unit_cod = element.fee_unit_cod;
                    feedetObj.amount = element.amount;
                    feedetObj.currency_cod = element.currency_cod;
                    feedetObj.fee_nam = oper_nam;
                    feedetObj.fee_tim = dto.leav_port_tim;
                    feedetObj.fee_in_out = element.fee_in_out;
                    // feedetObj.bill_no = findPlan.bill_no;
                    feedetObj.lease_sn = dto.out_truck_sn;
                    await this.businessService.createFeedet(
                        feedetObj,
                        queryRunner,
                    );
                }

            }
            // 修改计划
            await queryRunner.manager.createQueryBuilder()
                .update(CntrPlan)
                .set({
                    cntr_work_num: (findPlan.cntr_work_num ?? 0) + dto.cntrs.length,
                    finish_id:
                        (findPlan.cntr_work_num ?? 0) + dto.cntrs.length >=
                            findPlan.cntr_num
                            ? 'Y'
                            : 'N',
                })
                .where('id = :plan_id', { plan_id: dto.out_truck_sn })
                .execute();


            await queryRunner.commitTransaction();
            const mailOption: EmailType = {};
            const ownermail = await this.datasource.createQueryBuilder()
                .select(['email', 'client_nam_c'])
                .from(Client, 'c_client_cod')
                .where('id = :id', { id: findPlan.cntr_owner })
                .getRawOne();
            const cfsmail = await this.datasource.createQueryBuilder()
                .select(['email', 'cfs_nam_c'])
                .from(CyCfs, 'c_cy_cfs')
                .where('id = :id', { id: findPlan.cfs_cod })
                .getRawOne();

            if (ownermail?.email) {
                mailOption.to = `${ownermail['email']}`;
                mailOption.subject = '箱出场';
                mailOption.text = `
                        出场计划号：${dto.out_truck_sn}
                        出场时间： ${dayjs(dto.leav_port_tim).format('YYYY-MM-DD HH:mm:ss')}
                        箱号: ${dto.cntrs}
                        尺寸： ${findPlan.cntr_siz_cod}
                        箱型： ${findPlan.cntr_typ_cod}
                        堆场： ${cfsmail.cfs_nam_c}
                    `;
                const sendR = await this.sharedService.sendMail(mailOption);
            }
            return {
                code: ResponseCode.SuccessWithInfo,
                msg: ['出场成功']
            }
        } catch (err) {
            await queryRunner.rollbackTransaction();
            throw err;
        } finally {
            await queryRunner.release();
        }
    }
    /**
     * 起租箱出场
     * @param dto 
     * @param cfs_id 
     * @param oper_nam 
     * @returns 
     */
    async leasegateout(dto: GateOutCntrDto, cfs_id: number, oper_nam: string): Promise<ResponseJson<null, null>> {
        const queryRunner = this.datasource.createQueryRunner();
        await queryRunner.connect();
        await queryRunner.startTransaction();
        try {
            // 计划信息
            const findPlan = await queryRunner.manager.createQueryBuilder<CntrLeasePlan>(CntrLeasePlan, 'v_truck_cntr_outplan')
                .select(['cntr_num', 'cntr_corp_cod', 'cntr_work_num', 'bill_no', 'cfs_cod', 'finish_id',
                    'cntr_siz_cod', 'cntr_typ_cod', 'dam_id', 'cntr_owner'])
                .where('id = :id', { id: dto.out_truck_sn })
                .getRawOne();
            // 计划费用信息
            const planFees = await queryRunner.manager.createQueryBuilder<CntrPlanFee>(CntrPlanFee, 'truck_cntr_plan_fee')
                .where('truck_sn = :truck_sn', { truck_sn: dto.out_truck_sn })
                .getMany();
            if (isNil(findPlan)) {
                throw new Error('未选择计划， 出场失败');
            }
            if (findPlan.finish_id === 'Y') {
                throw new Error(`起租计划${dto.out_truck_sn}已完成，出场失败`);
            }
            if (findPlan.cntr_num < (findPlan.cntr_work_num ?? 0) + dto.cntrs.length) {
                throw new Error(`出场箱量超过未完成箱量，出场失败`);
            }
            for (let index = 0; index < dto.cntrs.length; index++) {
                const cntrString = dto.cntrs[index];
                const planCntr = await queryRunner.manager.createQueryBuilder<CntrPlanCntr>(CntrPlanCntr, 'truck_cntr_plan_cntr')
                    .select(['id'])
                    .where('truck_sn = :truck_sn', { truck_sn: dto.out_truck_sn })
                    .andWhere('cntr = :cntr', { cntr: cntrString })
                    .andWhere("used_id = 'N'")
                    .getRawOne();

                const cntr = await queryRunner.manager.createQueryBuilder<Cntr>(Cntr, 'cntr_file')
                    .select(['id', 'cfs_cod', 'cntr_owner', 'cntr_siz_cod', 'cntr_typ_cod', 'dam_id'])
                    .where('cntr = :cntr', { cntr: cntrString })
                    .andWhere("current_stat = '2'")
                    .getRawOne();
                if (isNil(cntr)) {
                    throw new Error(`箱号${cntrString}非在场箱， 出场失败`);
                }
                if (isNil(planCntr)) {
                    throw new Error(`箱号${cntrString}非计划预订箱，出场失败`);
                }
                if (!(cntr.cfs_cod === cfs_id && findPlan.cfs_cod === cfs_id)) {
                    throw new Error(`箱号${cntrString}与计划站点不一致， 出场失败`);
                }
                if (cntr.cntr_siz_cod !== findPlan.cntr_siz_cod) {
                    throw new Error(`箱号${cntrString}与计划尺寸不一致， 出场失败`);
                }
                if (cntr.cntr_typ_cod !== findPlan.cntr_typ_cod) {
                    throw new Error(`箱号${cntrString}与计划箱型不一致， 出场失败`);
                }
                /* if (cntr.dam_id !== findPlan.dam_id) {
                    throw new Error(`箱号${cntrString}与计划箱况不一致， 出场失败`);
                } */
                if (cntr.cntr_owner !== findPlan.cntr_owner) {
                    throw new Error(`箱号${cntrString}与计划箱主不一致， 出场失败`);
                }
                // 修改 cntr_file.current_stat
                await this.containerService.updateCntr(
                    { id: cntr.id, current_stat: '1', cfs_cod: null },
                    queryRunner,
                );
                const leaseCntr = {} as unknown as CntrLeaseDto;
                leaseCntr.cntr_no = cntr.id;
                leaseCntr.lease_sn = dto.out_truck_sn;

                leaseCntr.out_date = dto.leav_port_tim;
                leaseCntr.out_cfs = cntr.cfs_cod;
                leaseCntr.out_truck_no_c = dto.out_truck_no_c;
                leaseCntr.out_driver_tel = dto.out_truck_tel;
                // 插入 cntr_lease 新记录
                await this.containerService.createCntrLease(leaseCntr, queryRunner);
                // 修改 truck_cntr_plan_cntr used_id
                await queryRunner.manager.createQueryBuilder()
                    .update(CntrPlanCntr)
                    .set({
                        used_id: 'Y'
                    })
                    .where('id = :id', { id: planCntr.id })
                    .execute();
                // 插入 fee_det 新记录
                for (let index = 0; index < planFees.length; index++) {
                    const feedetObj = {} as unknown as FeedetDto;
                    const element = planFees[index];
                    if (['0105', '0108'].includes(element.fee_cod)) {
                        continue;
                    }
                    // feedetObj.out_truck_sn = planID;
                    feedetObj.cntr_no = cntr.id;
                    feedetObj.fee_owner = element.fee_owner;
                    feedetObj.fee_typ_cod = element.fee_typ_cod;
                    feedetObj.fee_cod = element.fee_cod;
                    feedetObj.fee_unit_cod = element.fee_unit_cod;
                    feedetObj.amount = element.amount;
                    feedetObj.currency_cod = element.currency_cod;
                    feedetObj.fee_nam = oper_nam;
                    feedetObj.fee_tim = dto.leav_port_tim;
                    feedetObj.fee_in_out = element.fee_in_out;
                    feedetObj.bill_no = findPlan.bill_no;
                    await this.businessService.createFeedet(
                        feedetObj,
                        queryRunner,
                    );
                }
            }


            // 修改 truck_cntr_plan 完成箱量
            await queryRunner.manager.createQueryBuilder()
                .update(CntrPlan)
                .set({
                    cntr_work_num: (findPlan.cntr_work_num ?? 0) + dto.cntrs.length,
                    finish_id:
                        (findPlan.cntr_work_num ?? 0) + dto.cntrs.length >=
                            findPlan.cntr_num
                            ? 'Y'
                            : 'N',
                })
                .where('id = :plan_id', { plan_id: dto.out_truck_sn })
                .execute();


            await queryRunner.commitTransaction();

            const mailOption: EmailType = {};
            const ownermail = await this.datasource.createQueryBuilder()
                .select(['email', 'client_nam_c'])
                .from(Client, 'c_client_cod')
                .where('id = :id', { id: findPlan.cntr_owner })
                .getRawOne();
            const corpmail = await this.datasource.createQueryBuilder()
                .select(['email', 'client_nam_c'])
                .from(Client, 'c_client_cod')
                .where('id = :id', { id: findPlan.cntr_corp_cod })
                .getRawOne();
            const cfsmail = await this.datasource.createQueryBuilder()
                .select(['email', 'cfs_nam_c'])
                .from(CyCfs, 'c_cy_cfs')
                .where('id = :id', { id: findPlan.cfs_cod })
                .getRawOne();

            if (ownermail?.email && corpmail?.email) {
                mailOption.to = `${ownermail['email']};${corpmail['email']}`;
                mailOption.subject = '起租箱出场';
                mailOption.text = `
                        起租计划号：${dto.out_truck_sn}
                        出场时间： ${dayjs(dto.leav_port_tim).format('YYYY-MM-DD HH:mm:ss')}
                        箱号: ${dto.cntrs}
                        尺寸： ${findPlan.cntr_siz_cod}
                        箱型： ${findPlan.cntr_typ_cod}
                        堆场： ${cfsmail.cfs_nam_c}
                    `;
                const sendR = await this.sharedService.sendMail(mailOption);
            }
            return {
                code: ResponseCode.SuccessWithInfo,
                msg: ['起租出场成功']
            }
        } catch (err) {
            await queryRunner.rollbackTransaction();
            throw err;
        } finally {
            await queryRunner.release();
        }
    }
    /**
     * 退租箱进场
     * @param dto 
     * @param cfs_id 
     * @param oper_nam 
     * @returns 
     */
    async rentgatein(dto: RentInCntrDto, cfs_id: number, oper_nam: string): Promise<ResponseJson<null, null>> {
        const queryRunner = this.datasource.createQueryRunner();
        await queryRunner.connect();
        await queryRunner.startTransaction();
        try {
            const findPlan = await queryRunner.manager.createQueryBuilder<CntrInPlan>(CntrInPlan, 'v_truck_cntr_inplan')
                .select(['cntr_num', 'cntr_corp_cod', 'cntr_work_num', 'cfs_cod', 'finish_id',
                    'cntr_siz_cod', 'cntr_typ_cod'])
                .where('id = :id', { id: dto.rent_sn })
                .getRawOne();

            const planCntr = await queryRunner.manager.createQueryBuilder<CntrPlanCntr>(CntrPlanCntr, 'truck_cntr_plan_cntr')
                .select(['id'])
                .where('truck_sn = :truck_sn', { truck_sn: dto.rent_sn })
                .andWhere('cntr = :cntr', { cntr: dto.cntr })
                .andWhere("used_id = 'N'")
                .getRawOne();

            const planFees = await queryRunner.manager.createQueryBuilder<CntrPlanFee>(CntrPlanFee, 'truck_cntr_plan_fee')
                .where('truck_sn = :truck_sn', { truck_sn: dto.rent_sn })
                .getMany();

            const cntr = await queryRunner.manager.createQueryBuilder<Cntr>(Cntr, 'cntr_file')
                .select(['id', 'cntr_owner', 'cntr_siz_cod', 'cntr_typ_cod'])
                .where('cntr = :cntr', { cntr: dto.cntr })
                .andWhere("current_stat = '1'")
                .getRawOne();

            const rentCntr = await queryRunner.manager.createQueryBuilder<CntrLease>(CntrLease, 'cntr_lease')
                .select(['id', 'lease_sn'])
                .where('cntr_no = :cntr_no', { cntr_no: cntr.id })
                .andWhere('rent_sn is null')
                .getRawOne();


            if (isNil(cntr)) {
                throw new Error('非出租箱， 进场失败');
            }
            if (isNil(findPlan)) {
                throw new Error('未选择计划， 进场失败');
            }
            if (isNil(planCntr)) {
                throw new Error('非计划预订箱，进场失败');
            }
            if (isNil(rentCntr)) {
                throw new Error('出租箱查找错误，进场失败');
            }
            if (!(findPlan.cfs_cod === cfs_id)) {
                throw new Error('当前站点与计划站点不一致， 进场失败');
            }
            if (cntr.cntr_siz_cod !== findPlan.cntr_siz_cod) {
                throw new Error('尺寸不一致， 出场失败');
            }
            if (cntr.cntr_typ_cod !== findPlan.cntr_typ_cod) {
                throw new Error('箱型不一致， 出场失败');
            }

            if (findPlan.finish_id === 'Y') {
                throw new Error(`退租计划${dto.rent_sn}已完成，进场失败`);
            }
            if (findPlan.cntr_num - (findPlan.cntr_work_num ?? 0) <= 0) {
                throw new Error(`退租计划${dto.rent_sn}已完成，进场失败`);
            }
            // 修改 cntr_file.current_stat
            await this.containerService.updateCntr(
                { id: cntr.id, current_stat: '2', cfs_cod: cfs_id },
                queryRunner,
            );

            // 创建箱动态
            const cntrStatObj = {} as unknown as PortCntrStatDto;
            cntrStatObj.cntr_no = cntr.id;
            cntrStatObj.cntr = dto.cntr;

            cntrStatObj.cntr_stat_cod = EITZJC;
            cntrStatObj.stat_tim = dto.back_date;
            cntrStatObj.cfs_cod = findPlan.cfs_cod;
            cntrStatObj.plan_id = dto.rent_sn;
            cntrStatObj.dam_id = dto.dam_id;
            await this.containerService.createPortCntrStat(cntrStatObj, queryRunner);
            const leaseCntr = {} as unknown as LeaseCntrBackDto;
            // leaseCntr.id = rentCntr.id;
            leaseCntr.rent_sn = dto.rent_sn;
            leaseCntr.back_cfs = cfs_id;
            leaseCntr.back_date = dto.back_date;
            leaseCntr.back_truck_no_c = dto.back_truck_no_c;
            leaseCntr.back_driver_tel = dto.back_driver_tel;
            // 修改 cntr_lease rent_sn back_date back_cfs back_truck_no_c back_truck_tel
            await queryRunner.manager
                .createQueryBuilder()
                .update(CntrLease)
                .set(leaseCntr)
                .where('id = :id', { id: rentCntr.id })
                .execute();


            // 修改 truck_cntr_plan 完成箱量
            await queryRunner.manager.createQueryBuilder()
                .update(CntrPlan)
                .set({
                    cntr_work_num: (findPlan.cntr_work_num ?? 0) + 1,
                    finish_id:
                        (findPlan.cntr_work_num ?? 0) + 1 >=
                            findPlan.cntr_num
                            ? 'Y'
                            : 'N',
                })
                .where('id = :plan_id', { plan_id: dto.rent_sn })
                .execute();
            // 修改 truck_cntr_plan_cntr used_id
            await queryRunner.manager.createQueryBuilder()
                .update(CntrPlanCntr)
                .set({
                    used_id: 'Y'
                })
                .where('id = :id', { id: planCntr.id })
                .execute();
            // 插入 fee_det 新记录
            for (let index = 0; index < planFees.length; index++) {
                const feedetObj = {} as unknown as FeedetDto;
                const element = planFees[index];
                if (['0105', '0108'].includes(element.fee_cod)) {
                    continue;
                }
                // feedetObj.out_truck_sn = planID;
                feedetObj.cntr_no = cntr.id;
                feedetObj.fee_owner = element.fee_owner;
                feedetObj.fee_typ_cod = element.fee_typ_cod;
                feedetObj.fee_cod = element.fee_cod;
                feedetObj.fee_unit_cod = element.fee_unit_cod;
                feedetObj.amount = element.amount;
                feedetObj.currency_cod = element.currency_cod;
                feedetObj.fee_nam = oper_nam;
                feedetObj.fee_tim = dto.back_date;
                feedetObj.fee_in_out = element.fee_in_out;
                feedetObj.bill_no = findPlan.bill_no;
                await this.businessService.createFeedet(
                    feedetObj,
                    queryRunner,
                );
            }

            await queryRunner.commitTransaction();

            const mailOption: EmailType = {};
            const ownermail = await this.datasource.createQueryBuilder()
                .select(['email', 'client_nam_c'])
                .from(Client, 'c_client_cod')
                .where('id = :id', { id: cntr.cntr_owner })
                .getRawOne();

            const cfsmail = await this.datasource.createQueryBuilder()
                .select(['email', 'cfs_nam_c'])
                .from(CyCfs, 'c_cy_cfs')
                .where('id = :id', { id: cfs_id })
                .getRawOne();

            if (ownermail?.email) {
                mailOption.to = `${ownermail['email']}`;
                mailOption.subject = '退租箱进场';
                mailOption.text = `
                        退租计划号：${dto.rent_sn}
                        进场时间： ${dayjs(dto.back_date).format('YYYY-MM-DD HH:mm:ss')}
                        箱号: ${dto.cntr}
                        尺寸： ${cntr.cntr_siz_cod}
                        箱型： ${cntr.cntr_typ_cod}
                        堆场： ${cfsmail.cfs_nam_c}
                    `;
                const sendR = await this.sharedService.sendMail(mailOption);
            }
            return {
                code: ResponseCode.SuccessWithInfo,
                msg: ['退租进场成功']
            }
        } catch (err) {
            await queryRunner.rollbackTransaction();
            throw err;
        } finally {
            await queryRunner.release();
        }
    }
    /**
     * 调箱进场
     * @param dto 
     * @param cfs_id 
     * @param oper_nam 
     * @returns 
     */
    async transgatein(dto: RentInCntrDto, cfs_id: number, oper_nam: string): Promise<ResponseJson<null, null>> {
        const queryRunner = this.datasource.createQueryRunner();
        await queryRunner.connect();
        await queryRunner.startTransaction();
        try {
            const findPlan = await queryRunner.manager.createQueryBuilder<CntrInPlan>(CntrInPlan, 'v_truck_cntr_inplan')
                .select(['cntr_num', 'cntr_corp_cod', 'cntr_work_num', 'cfs_cod', 'finish_id',
                    'cntr_siz_cod', 'cntr_typ_cod'])
                .where('id = :id', { id: dto.rent_sn })
                .getRawOne();

            const planCntr = await queryRunner.manager.createQueryBuilder<CntrPlanCntr>(CntrPlanCntr, 'truck_cntr_plan_cntr')
                .select(['id'])
                .where('truck_sn = :truck_sn', { truck_sn: dto.rent_sn })
                .andWhere('cntr = :cntr', { cntr: dto.cntr })
                .andWhere("used_id = 'N'")
                .getRawOne();

            const planFees = await queryRunner.manager.createQueryBuilder<CntrPlanFee>(CntrPlanFee, 'truck_cntr_plan_fee')
                .where('truck_sn = :truck_sn', { truck_sn: dto.rent_sn })
                .getMany();

            const cntr = await queryRunner.manager.createQueryBuilder<Cntr>(Cntr, 'cntr_file')
                .select(['id', 'cntr_owner', 'cntr_siz_cod', 'cntr_typ_cod'])
                .where('cntr = :cntr', { cntr: dto.cntr })
                .andWhere("current_stat = '3'")
                .getRawOne();



            if (isNil(cntr)) {
                throw new Error('非离场箱， 进场失败');
            }
            if (isNil(findPlan)) {
                throw new Error('未选择计划， 进场失败');
            }
            if (isNil(planCntr)) {
                throw new Error('非计划预订箱，进场失败');
            }

            if (!(findPlan.cfs_cod === cfs_id)) {
                throw new Error('当前站点与计划站点不一致， 进场失败');
            }
            if (cntr.cntr_siz_cod !== findPlan.cntr_siz_cod) {
                throw new Error('尺寸不一致， 出场失败');
            }
            if (cntr.cntr_typ_cod !== findPlan.cntr_typ_cod) {
                throw new Error('箱型不一致， 出场失败');
            }

            if (findPlan.finish_id === 'Y') {
                throw new Error(`计划${dto.rent_sn}已完成，进场失败`);
            }
            if (findPlan.cntr_num - (findPlan.cntr_work_num ?? 0) <= 0) {
                throw new Error(`计划${dto.rent_sn}已完成，进场失败`);
            }
            // 修改 cntr_file.current_stat
            /* await this.containerService.updateCntr(
                { id: cntr.id, cfs_cod: cfs_id },
                queryRunner,
            ); */

            // 创建箱动态
            const cntrStatObj = {} as unknown as PortCntrStatDto;
            cntrStatObj.cntr_no = cntr.id;
            cntrStatObj.cntr = dto.cntr;

            cntrStatObj.cntr_stat_cod = EIZYXT;
            cntrStatObj.stat_tim = dto.back_date;
            cntrStatObj.cfs_cod = findPlan.cfs_cod;
            cntrStatObj.plan_id = dto.rent_sn;
            cntrStatObj.dam_id = dto.dam_id;
            await this.containerService.createPortCntrStat(cntrStatObj, queryRunner);

            // 修改 truck_cntr_plan 完成箱量
            await queryRunner.manager.createQueryBuilder()
                .update(CntrPlan)
                .set({
                    cntr_work_num: (findPlan.cntr_work_num ?? 0) + 1,
                    finish_id:
                        (findPlan.cntr_work_num ?? 0) + 1 >=
                            findPlan.cntr_num
                            ? 'Y'
                            : 'N',
                })
                .where('id = :plan_id', { plan_id: dto.rent_sn })
                .execute();
            // 修改 truck_cntr_plan_cntr used_id
            await queryRunner.manager.createQueryBuilder()
                .update(CntrPlanCntr)
                .set({
                    used_id: 'Y'
                })
                .where('id = :id', { id: planCntr.id })
                .execute();
            // 插入 fee_det 新记录
            for (let index = 0; index < planFees.length; index++) {
                const feedetObj = {} as unknown as FeedetDto;
                const element = planFees[index];
                if (['0105', '0108'].includes(element.fee_cod)) {
                    continue;
                }
                // feedetObj.out_truck_sn = planID;
                feedetObj.cntr_no = cntr.id;
                feedetObj.fee_owner = element.fee_owner;
                feedetObj.fee_typ_cod = element.fee_typ_cod;
                feedetObj.fee_cod = element.fee_cod;
                feedetObj.fee_unit_cod = element.fee_unit_cod;
                feedetObj.amount = element.amount;
                feedetObj.currency_cod = element.currency_cod;
                feedetObj.fee_nam = oper_nam;
                feedetObj.fee_tim = dto.back_date;
                feedetObj.fee_in_out = element.fee_in_out;
                feedetObj.bill_no = findPlan.bill_no;
                await this.businessService.createFeedet(
                    feedetObj,
                    queryRunner,
                );
            }

            await queryRunner.commitTransaction();

            const mailOption: EmailType = {};
            const ownermail = await this.datasource.createQueryBuilder()
                .select(['email', 'client_nam_c'])
                .from(Client, 'c_client_cod')
                .where('id = :id', { id: cntr.cntr_owner })
                .getRawOne();

            const cfsmail = await this.datasource.createQueryBuilder()
                .select(['email', 'cfs_nam_c'])
                .from(CyCfs, 'c_cy_cfs')
                .where('id = :id', { id: cfs_id })
                .getRawOne();

            if (ownermail?.email) {
                mailOption.to = `${ownermail['email']}`;
                mailOption.subject = '调箱进场';
                mailOption.text = `
                        调箱计划号：${dto.rent_sn}
                        进场时间： ${dayjs(dto.back_date).format('YYYY-MM-DD HH:mm:ss')}
                        箱号: ${dto.cntr}
                        尺寸： ${cntr.cntr_siz_cod}
                        箱型： ${cntr.cntr_typ_cod}
                        堆场： ${cfsmail.cfs_nam_c}
                    `;
                const sendR = await this.sharedService.sendMail(mailOption);
            }
            return {
                code: ResponseCode.SuccessWithInfo,
                msg: ['调箱进场成功']
            }
        } catch (err) {
            await queryRunner.rollbackTransaction();
            throw err;
        } finally {
            await queryRunner.release();
        }
    }
    async getFixListByCntr(cntr_no: number, cfs_id: number): Promise<ResponseJson<{ fixlists: CntrFixItem[], total_money: number }, FixReply[]>> {
        const cfs_cod = await this.datasource.manager.createQueryBuilder<Cntr>(Cntr, 'cntr_file')
            .select('cfs_cod', 'cfs_cod')
            .where('id = :id', { id: cntr_no })
            .getRawOne();
        if (!(parseInt(cfs_cod.cfs_cod) === cfs_id)) {
            throw new Error(`非此站点箱`);
        }
        const fixlists = await this.datasource.manager.createQueryBuilder<CntrFixItem>(CntrFixItem, 'fix_list')
            .where('cntr_no = :cntr_no', { cntr_no: cntr_no })
            .getMany();
        const sumAmount = await this.datasource.manager.createQueryBuilder<CntrFixItem>(CntrFixItem, 'fix_list')
            .select('sum(total_money) as total_money')
            .where('cntr_no = :cntr_no', { cntr_no: cntr_no })
            .getRawOne();
        const fixReplys = await this.datasource.manager.createQueryBuilder<FixReply>(FixReply, 'fix_reply')
            .where('cntr_no = :cntr_no', { cntr_no: cntr_no })
            .orderBy('msg_time')
            .getMany();
        return {
            code: ResponseCode.SuccessNoMsg,
            obj: {
                fixlists: fixlists,
                total_money: sumAmount.total_money
            },
            ext: fixReplys
        }
    }

    async createCntrFixItem(dto: CntrFixItemDto, cfs_id: number): Promise<ResponseJson<CntrFixItem, null>> {
        const cntr = await this.datasource.manager.createQueryBuilder<Cntr>(Cntr, 'cntr_file')
            .select(['cfs_cod as cfs_cod', 'repair_reply_id'])
            .where('id = :id', { id: dto.cntr_no })
            .getRawOne();
        if (!(parseInt(cntr.cfs_cod) === cfs_id)) {
            throw new Error(`非此站点箱`);
        }
        if (cntr.repair_reply_id === 'R') {
            throw new Error('此箱已批复，不能增加修理项目');
        }
        return await this.crud.create<CntrFixItem, CntrFixItemDto>(CntrFixItem, dto);
    }
    async updateCntrFixItem(dto: UpdateCntrFixItemDto, cfs_id: number): Promise<ResponseJson<CntrFixItem, null>> {
        const cntr = await this.datasource.manager.createQueryBuilder<Cntr>(Cntr, 'cntr_file')
            .select(['cfs_cod as cfs_cod', 'repair_reply_id'])
            .where('id = :id', { id: dto.cntr_no })
            .getRawOne();
        if (!(parseInt(cntr.cfs_cod) === cfs_id)) {
            throw new Error(`非此站点箱`);
        }
        if (cntr.repair_reply_id === 'R') {
            throw new Error('此箱已批复，不能修改修理项目');
        }
        return await this.crud.update(CntrFixItem, omit(dto, ['cntr_no']));
    }
    async deleteCntrFixItems(dto: DeleteCntrFixItemsDto, cfs_id: number): Promise<ResponseJson> {
        const cntr = await this.datasource.manager.createQueryBuilder<Cntr>(Cntr, 'cntr_file')
            .select(['cfs_cod as cfs_cod', 'repair_reply_id'])
            .where('id = :id', { id: dto.cntr_no })
            .getRawOne();
        if (!(parseInt(cntr.cfs_cod) === cfs_id)) {
            throw new Error(`非此站点箱`);
        }
        if (cntr.repair_reply_id === 'R') {
            throw new Error('此箱已批复，不能删除修理项目');
        }

        return await this.crud.delete<CntrFixItem>(CntrFixItem, dto);
    }

    async QuoteCntrFix(dto: DeleteDto, cfs_id: number, oper_nam: string): Promise<ResponseJson> {
        const queryRunner = this.datasource.createQueryRunner();
        await queryRunner.connect();
        await queryRunner.startTransaction();
        try {
            const sysdate = new Date();
            const mails: {
                cntrowner: number,
                cntrownerEmail: string,
                msg: string
            }[] = [];
            for (let index = 0; index < dto.ids.length; index++) {
                const element = dto.ids[index];
                const cntr = await queryRunner.manager.createQueryBuilder<Cntr>(Cntr, 'cntr_file')
                    .select(['cfs_cod as cfs_cod', 'repair_reply_id', 'cntr as cntr', 'cntr_owner'])
                    .where('id = :id', { id: element })
                    .getRawOne();
                if (!(parseInt(cntr.cfs_cod) === cfs_id)) {
                    throw new Error(`箱号${cntr.cntr}非此站点箱`);
                }
                if (cntr.repair_reply_id === 'R') {
                    throw new Error(`箱号${cntr.cntr}已批复，不能提交报价`);
                }
                const fixListCount = await queryRunner.manager.createQueryBuilder<CntrFixItem>(CntrFixItem, 'fix_list')
                    // .select()
                    .where('cntr_no = :cntr_no', { cntr_no: element })
                    .getCount();
                // console.log('fixListCount', fixListCount);
                if (fixListCount <= 0) {
                    throw new Error(`箱号${cntr.cntr},没有维修明细，不能提交`);
                }
                await queryRunner.manager.createQueryBuilder()
                    .insert()
                    .into(FixReply)
                    .values({
                        cntr_no: element,
                        msg_time: sysdate,
                        oper_name: oper_nam,
                        reply_id: RepairStatusType.S,
                        msg: '提交报价'
                    })
                    .execute();
                await queryRunner.manager.createQueryBuilder()
                    .update(Cntr)
                    .set({
                        repair_reply_id: 'S',
                        repair_tim: sysdate
                    })
                    .where('id = :id', { id: element })
                    .execute();
                const findMailIndex = mails.findIndex((m) => m.cntrowner === cntr.cntr_owner);

                if (findMailIndex > -1) {
                    mails[findMailIndex].msg += ` ${cntr.cntr}`
                } else {
                    const ownermail = await this.datasource.createQueryBuilder()
                        .select(['email', 'client_nam_c'])
                        .from(Client, 'c_client_cod')
                        .where('id = :id', { id: cntr.cntr_owner })
                        .getRawOne();

                    mails.push({
                        cntrowner: cntr.cntr_owner,
                        cntrownerEmail: ownermail['email'],
                        msg: `修箱报价箱号：${cntr.cntr}`
                    })
                }
            }

            await queryRunner.commitTransaction();


            const mailOption: EmailType = {};
            for (let index = 0; index < mails.length; index++) {
                const element = mails[index];
                mailOption.to = `${element.cntrownerEmail}`;
                mailOption.subject = '修箱报价提交';
                mailOption.text = element.msg;
                const sendR = await this.sharedService.sendMail(mailOption);
            }
            return {
                code: ResponseCode.SuccessWithInfo,
                msg: ['提交成功']
            }
        } catch (err) {
            await queryRunner.rollbackTransaction();
            throw err;
        } finally {
            await queryRunner.release();
        }
    }
}